package work.wiwf.web.cfg.inter;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.ssssssss.magicapi.core.context.RequestEntity;
import org.ssssssss.magicapi.core.interceptor.RequestInterceptor;
import org.ssssssss.magicapi.core.model.ApiInfo;
import org.ssssssss.magicapi.core.model.JsonBean;
import org.ssssssss.magicapi.core.model.Options;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletResponse;
import org.ssssssss.script.MagicScriptContext;

import work.wiwf.web.model.sys.bean.entity.SysMenuEntity;
import work.wiwf.web.model.sys.bean.vo.SysRoleVo;
import work.wiwf.web.model.sys.bean.vo.SysUserVo;
import work.wiwf.web.model.sys.service.SysTokenService;

@Component
public class MagicReqInterceptor implements RequestInterceptor{

	@Resource
	private SysTokenService tokenService;
	
	/**
	 * 请求之前执行
	 *
	 * @param requestEntity 请求对象
	 * @return 当返回对象时，直接将此对象返回到页面，返回null时，继续执行后续操作
	 */
	@Override
	public Object preHandle(RequestEntity requestEntity) throws Exception {
		return preHandle(requestEntity.getApiInfo(), requestEntity.getMagicScriptContext(), requestEntity.getRequest(), requestEntity.getResponse());
	}

	/**
	 * 请求之前执行
	 *
	 * @param info     接口信息
	 * @param context  脚本上下文
	 * @param mgRequest  HttpServletRequest
	 * @param mgResponse HttpServletResponse
	 * @return 当返回对象时，直接将此对象返回到页面，返回null时，继续执行后续操作
	 * @throws Exception 处理失败时抛出的异常
	 */
	@Override
	public Object preHandle(ApiInfo info, MagicScriptContext context, MagicHttpServletRequest mgRequest, MagicHttpServletResponse mgResponse) throws Exception {
		// -- 接口被直接调用时 获取 token 的方式
		String token = mgRequest.getHeader("Magic-Token");
		if(ObjectUtils.isEmpty(token)) {
			token = tokenService.getToken();
		}
		
		// -- 需要登录接口
		if ("true".equals(info.getOptionValue(Options.REQUIRE_LOGIN))) {
			if (! ObjectUtils.isEmpty(token)) {
				if (ObjectUtils.isEmpty(tokenService.getTokenUser(token))) {
					return new JsonBean<>(401, "用户未登录");
				}
			} else {
				return new JsonBean<>(401, "用户未登录");
			}
		}
		
		// -- 需要权限接口
		String role = info.getOptionValue(Options.ROLE);
		String permission = info.getOptionValue(Options.PERMISSION);
		if (ObjectUtils.isEmpty(role) && ObjectUtils.isEmpty(permission)) {
			return null;
		} else {
			if (ObjectUtils.isEmpty(token)) {
				return new JsonBean<>(401, "用户未登录");
			}

			SysUserVo sysUserVo = tokenService.getTokenUser(token);
			List<SysRoleVo> roles = sysUserVo.getRoles();
			
			if (!ObjectUtils.isEmpty(permission) && !ObjectUtils.isEmpty(role)) {
				// 当对权限和角色都有要求时
				for (SysRoleVo sysRoleVo : roles) {
					String roleCode = sysRoleVo.getRoleCode();
					if (role.equalsIgnoreCase(roleCode)) {
						List<SysMenuEntity> menus = sysRoleVo.getMenus();
						for (SysMenuEntity menuEntity : menus) {
							String menuCode = menuEntity.getMenuCode();
							if(permission.equalsIgnoreCase(menuCode)) {
								return null;
							}
						}
					}
				}
			} else if (ObjectUtils.isEmpty(permission) == false) {
				for (SysRoleVo sysRoleVo : roles) {
					List<SysMenuEntity> menus = sysRoleVo.getMenus();
					for (SysMenuEntity menuEntity : menus) {
						String menuCode = menuEntity.getMenuCode();
						if(permission.equalsIgnoreCase(menuCode)) {
							return null;
						}
					}
				}
			} else if (ObjectUtils.isEmpty(role) == false) {
				for (SysRoleVo sysRoleVo : roles) {
					String roleCode = sysRoleVo.getRoleCode();
					if (role.equalsIgnoreCase(roleCode)) {
						return null;
					}
				}
			}
		}

		return new JsonBean<>(403, "用户权限不足");
	}


	/**
	 * 执行完毕之后执行
	 *
	 * @param info        接口信息
	 * @param context     脚本上下文
	 * @param returnValue 即将要返回到页面的值
	 * @param request     HttpServletRequest
	 * @param response    HttpServletResponse
	 * @return 返回到页面的对象, 当返回null时执行后续拦截器，否则直接返回该值，不执行后续拦截器
	 * @throws Exception 处理失败时抛出的异常
	 */
	@Override
	public Object postHandle(ApiInfo info, MagicScriptContext context, Object returnValue, MagicHttpServletRequest request, MagicHttpServletResponse response) throws Exception {
		return null;
	}

	/**
	 * 执行完毕之后执行
	 *
	 * @param requestEntity 请求对象
	 * @param returnValue   即将要返回到页面的值
	 * @return 返回到页面的对象, 当返回null时执行后续拦截器，否则直接返回该值，不执行后续拦截器
	 */
	@Override
	public Object postHandle(RequestEntity requestEntity, Object returnValue) throws Exception {
		return postHandle(requestEntity.getApiInfo(), requestEntity.getMagicScriptContext(), returnValue, requestEntity.getRequest(), requestEntity.getResponse());
	}

	/**
	 * 接口执行完毕之后执行
	 *
	 * @param requestEntity 请求对象
	 * @param returnValue   即将要返回到页面的值
	 * @param throwable     异常对象
	 */
	@Override
	public void afterCompletion(RequestEntity requestEntity, Object returnValue, Throwable throwable) {
		afterCompletion(requestEntity.getApiInfo(), requestEntity.getMagicScriptContext(), returnValue, requestEntity.getRequest(), requestEntity.getResponse(), throwable);
	}

	/**
	 * 接口执行完毕之后执行
	 *
	 * @param info        接口信息
	 * @param context     脚本上下文
	 * @param returnValue 即将要返回到页面的值
	 * @param request     HttpServletRequest
	 * @param response    HttpServletResponse
	 * @param throwable   异常对象
	 */
	@Override
	public void afterCompletion(ApiInfo info, MagicScriptContext context, Object returnValue, MagicHttpServletRequest request, MagicHttpServletResponse response, Throwable throwable) {

	}

}
